package org.bjf.modules.sys.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.bjf.cache.CacheNameConfig.RedisCacheEnum.Names;
import org.bjf.modules.core.service.BaseService;
import org.bjf.modules.sys.bean.SysRole;
import org.bjf.modules.sys.bean.SysRolePerm;
import org.bjf.modules.sys.mapper.SysRolePermMapper;
import org.bjf.modules.sys.query.SysRolePermQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author bjf
 * @date 2017/11/27
 */
@Service
@Slf4j
public class SysRolePermService extends BaseService<SysRolePermMapper, SysRolePerm, SysRolePermQuery> {

    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysRoleService roleService;

    @Override
    protected LambdaQueryWrapper<SysRolePerm> buildQuery(SysRolePermQuery q) {
        if (q == null) {
            return null;
        }
        LambdaQueryWrapper<SysRolePerm> qw = new LambdaQueryWrapper<>();
        qw.eq(q.getSysRoleId() != null, SysRolePerm::getSysRoleId, q.getSysRoleId());
        qw.eq(q.getModuleCode() != null, SysRolePerm::getAuthModuleCode, q.getModuleCode());
        qw.in(!CollectionUtils.isEmpty(q.getRoleIdList()), SysRolePerm::getSysRoleId, q.getRoleIdList());
        return qw;
    }

    /**
     * 检查用户是否有权限
     *
     * @param sysUserId  用户id
     * @param moduleCode 模块编码
     * @param permCode   权限编码
     */
    @Cacheable(value = Names.SYS, key = "'live:rbac:hasPerm:' + #sysUserId + ':' + #moduleCode+':' + #permCode")
    public boolean hasPerm(Long sysUserId, String moduleCode, String permCode) {
        //===1.取用户所有角色
        List<SysRole> roles = roleService.listByUser(sysUserId);
        if (roles.isEmpty()) {
            return false;
        }
        List<Long> roleIdList = roles.stream().map(SysRole::getId).collect(Collectors.toList());
        //===2.根据角色取出权限
        SysRolePermQuery query = new SysRolePermQuery()
                .setRoleIdList(roleIdList)
                .setModuleCode(moduleCode)
                .setPermCode(permCode);
        List<SysRolePerm> rolePerms = this.listAll(query);
        if (rolePerms.isEmpty()) {
            return false;
        }
        return true;
    }

    /**
     * 根据用户查询权限列表
     */
    @Cacheable(value = Names.SYS, key = "'live:rbac:listUserPerm' + #roleId")
    public List<SysRolePerm> listUserPerm(Long sysUserId) {
        //===1.查询用户角色
        List<SysRole> sysRoles = roleService.listByUser(sysUserId);
        return this.listRolesPerm(sysRoles.stream().map(SysRole::getId).collect(Collectors.toList()));
    }

    /**
     * 根据角色查询权限列表
     */
    @Cacheable(value = Names.SYS, key = "'live:rbac:listRolePerm' + #roleId")
    public List<SysRolePerm> listRolePerm(Long roleId) {
        //===1.根据角色取权限
        SysRolePermQuery query = new SysRolePermQuery().setSysRoleId(roleId);
        return this.listAll(query);
    }

    /**
     * 根据角色查询权限列表
     */
    public List<SysRolePerm> listRolesPerm(List<Long> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            Collections.emptyList();
        }
        //===1.根据角色取权限
        SysRolePermQuery query = new SysRolePermQuery().setRoleIdList(roleIds);
        return this.listAll(query);
    }

    /**
     * 全量更新角色的权限
     */
    @Transactional(rollbackFor = Exception.class)
    public void updatePerm(Long roleId, List<SysRolePerm> rolePerms) {
        //===1.先删除角色全部权限
        LambdaQueryWrapper<SysRolePerm> ew = new LambdaQueryWrapper<>();
        ew.eq(SysRolePerm::getSysRoleId, roleId);
        this.delete(ew);

        //===2.新增角色权限
        Map<String, List<SysRolePerm>> moduleGroup = rolePerms.stream().collect(Collectors.groupingBy(SysRolePerm::getAuthModuleCode));
        moduleGroup.forEach((module, list) -> this.addBatch(list));

        //===3.删除用户缓存
        sysUserService.clearUserCache();
    }


}
